//###########################################################################
//
// FILE:   main.c
//
// TITLE:  FIR FILTERING Example
//

//!
//! This example uses ePWM1 to generate a periodic ADC SOC on SEQ1.
//! one channel is converted, ADCINA2.
//!
//
//###########################################################################


#include "DSP28x_Project.h"     // Device Headerfile and Examples Include File
#include "DSP2833x_McBSP_DA.h"

//
// ADC module clock = HSPCLK/2*ADC_CKPS = 25.0MHz/(1*2) = 12.5MHz
//
#define ADC_CKPS   0x1
#define ADC_SHCLK  0xF   // S/H width in ADC module periods = 16 ADC clocks
#define AD_DA_BUF_SIZE 1024  //AD采样与DA转换数据矩阵的长度
#define AD_Bankup_BUF_SIZE 140  //AD采样备份数据矩阵的长度，AD_Bankup_BUF_SIZE = 滤波器最大的系数个数-1，本例中滤波器最大的系数阶数为139阶，共140个滤波系数，故AD_Bankup_BUF_SIZE = 140-1=139

//
// Function Prototypes
//
__interrupt void adc_isr(void);
void ADC_INT_InitConfig(void);
void ADC_SOC_ePWM_InitConfig(void);
void ADC_InitConfig(void);
void GPIO_InitConfig(void);
void MCBSPA_InitConfig(void);
void SPI_Init(void);
Uint16 SPI_Receive_Data(void);
void Filtering_Coff_Array_Processing(void);
void FIR_Filtering(void);

//
// Globals
//
Uint16 Working_Mode;
Uint16 SPI_Receive_DataArray[282];//SPI接收数据矩阵
//SPI_Receive_DataArray[0]表示滤波命令字节，=1表示滤波，=0表示不滤波
//SPI_Receive_DataArray[1]表示滤波系数长度字节
//SPI_Receive_DataArray[2]~SPI_Receive_DataArray[282]表示140个滤波系数，每两个字节表示一个滤波系数，且高字节在前，低字节在后
int16 Filtering_Coff_Array[140];//滤波系数矩阵，长度=滤波器最大阶数+1，本例中滤波器最大阶数为139阶，故滤波系数矩阵长度=139+1=140

Uint16 AD_Array_A[AD_DA_BUF_SIZE],AD_Array_B[AD_DA_BUF_SIZE];
Uint16 DA_Array_C[AD_DA_BUF_SIZE],DA_Array_D[AD_DA_BUF_SIZE];
Uint16 AD_Bankup_Array_A[AD_Bankup_BUF_SIZE],AD_Bankup_Array_B[AD_Bankup_BUF_SIZE];
Uint16 FLAG_AB,FLAG_Load;
Uint16 AD_Array_Load_Location,AD_Bankup_Array_Load_Location;
Uint16 Filter_Coff_Size;//滤波器系数个数
Uint16 Filter_Order;//滤波器阶数，滤波器阶数=滤波器系数个数-1
Uint16 AD_Bankup_Array_Start_Load_Location;
Uint16 DA_Array_Load_Location;

//
// Main
//
int main(void)
{
    Uint16 tempt_n;
    //
    // Step 1. Initialize System Control:
    // PLL, WatchDog, enable Peripheral Clocks
    // This example function is found in the DSP2833x_SysCtrl.c file.
    //
    InitSysCtrl();

    EALLOW;
    #if (CPU_FRQ_150MHZ)     // Default - 150 MHz SYSCLKOUT
        //
        // HSPCLK = SYSCLKOUT/2*ADC_MODCLK2 = 150/(2*3)   = 25.0 MHz
        //
        #define ADC_MODCLK 0x3
    #endif
    EDIS;
    //
    // Define ADCCLK clock frequency ( less than or equal to 25 MHz )
    // Assuming InitSysCtrl() has set SYSCLKOUT to 150 MHz
    //
    EALLOW;
    SysCtrlRegs.HISPCP.all = ADC_MODCLK;
    EDIS;

    //
    // Step 2. Initialize GPIO:
    // This example function is found in the DSP2833x_Gpio.c file and
    // illustrates how to set the GPIO to it's default state.
    //
    GPIO_InitConfig();
    InitMcbspaGpio();
    InitSpiaGpio();// Setup only the GP I/O only for SPI-A functionality

    //
    // Step 3. Clear all interrupts and initialize PIE vector table:
    // Disable CPU interrupts
    //
    DINT;

    //
    // Initialize the PIE control registers to their default state.
    // The default state is all PIE interrupts disabled and flags
    // are cleared.
    // This function is found in the DSP2833x_PieCtrl.c file.
    //
    InitPieCtrl();

    //
    // Disable CPU interrupts and clear all CPU interrupt flags:
    //
    IER = 0x0000;
    IFR = 0x0000;

    //
    // Initialize the PIE vector table with pointers to the shell Interrupt
    // Service Routines (ISR).
    // This will populate the entire table, even if the interrupt
    // is not used in this example.  This is useful for debug purposes.
    // The shell ISR routines are found in DSP2833x_DefaultIsr.c.
    // This function is found in DSP2833x_PieVect.c.
    //
    InitPieVectTable();

    //
    // Interrupts that are used in this example are re-mapped to
    // ISR functions found within this file.
    //
    EALLOW;  // This is needed to write to EALLOW protected register
    PieVectTable.ADCINT = &adc_isr;
    EDIS;    // This is needed to disable write to EALLOW protected registers

    //
    // Step 4. Initialize all the Device Peripherals:
    // This function is found in DSP2833x_InitPeripherals.c
    //
    // InitPeripherals(); // Not required for this example
    InitAdc();  // Init the ADC
    ADC_InitConfig();// Specific ADC setup for this example:

    //
    // Specific MCBSP setup for this example:
    //
    MCBSPA_InitConfig();
    McBSPA_TLV5636_Init();
    //

    // Specific SPI setup for this example:
    //
    SPI_Init();
    for(tempt_n=0;tempt_n<282;tempt_n++)
    {
        SPI_Receive_DataArray[tempt_n] = 0;
    }

    // Step 5. User specific code, enable interrupts:
    //
    Working_Mode = 0;//默认为非滤波工作模式
    while(1)
    {
        while(Working_Mode == 0)//非滤波模式
        {
            while(SPI_Receive_Data()==0);
            if(SPI_Receive_DataArray[0]==1)
            {
                //滤波系数矩阵处理
                Filtering_Coff_Array_Processing();
                //滤波参数处理
                AD_Bankup_Array_Start_Load_Location = AD_DA_BUF_SIZE - Filter_Coff_Size;
                AD_Bankup_Array_Load_Location = 0;
                Filter_Order = Filter_Coff_Size - 1;
                AD_Array_Load_Location = Filter_Order;
                DA_Array_Load_Location = Filter_Order;
                FLAG_AB=0xFFFF;
                FLAG_Load=1;
                Working_Mode = 1;//转换为滤波工作模式
            }
        }
        while(Working_Mode == 1)//滤波模式
        {
            //滤波一帧AD采样数据
            FIR_Filtering();
            //查询是否有来自MCU的改变滤波参数命令
            if(SPI_Receive_Data()!=0)
            {
                if(SPI_Receive_DataArray[0]==0)
                {
                    Working_Mode = 0;//转换为非滤波工作模式
                }
            }

        }

    }
}

//
// Configure SPI
//
void
SPI_Init(void)
{
    //
    // Initialize SPI registers
    //
    EALLOW;
    SpiaRegs.SPICCR.all=0x0007; // Reset SPI, 8-bit character, SPI loop back mode disabled锟斤拷CLOCK POLARITY = 0
    SpiaRegs.SPICTL.all=0x000E; // Disables interrupt, Master/Slave XMIT enabled锟斤拷Enables transmission For the 4-pin option锟斤拷CLOCK PHASE =1锟斤拷SPICLK signal delayed by one half-cycle
    SpiaRegs.SPIBRR=0x004B;     // Baud rate =150MHz/4/(75+1)=0.4934MHz
    //SpiaRegs.SPICCR.bit.SPISWRESET=1;  // Enable SPI
    SpiaRegs.SPIPRI.bit.FREE=1;    //Free run, continue SPI operation regardless of suspend or when the suspend occurred
    EDIS;
}

//
// Configure ADCINT in PIE
//
void
ADC_INT_InitConfig(void)
{
    //
    // Enable ADCINT in PIE
    //
    PieCtrlRegs.PIEIER1.bit.INTx6 = 1;
    IER |= M_INT1;      // Enable CPU Interrupt 1
    EINT;               // Enable Global interrupt INTM
    ERTM;               // Enable Global realtime interrupt DBGM

    //
    // Enable SOCA from ePWM to start SEQ1
    //
    AdcRegs.ADCTRL2.bit.EPWM_SOCA_SEQ1 = 1;
    AdcRegs.ADCTRL2.bit.INT_ENA_SEQ1 = 1;  // Enable SEQ1 interrupt (every EOS)
}

//
// Configure ePWM
//
void
ADC_SOC_ePWM_InitConfig(void)
{
    //
    // Assumes ePWM1 clock is already enabled in InitSysCtrl();
    //
    EPwm1Regs.ETSEL.bit.SOCAEN = 1;     // Enable SOC on A group
    EPwm1Regs.ETSEL.bit.SOCASEL = 2;    // Select SOC from the event time-base counter equal to period (TBCTR = TBPRD)
    EPwm1Regs.ETPS.bit.SOCAPRD = 1;     // Generate pulse on 1st event
    EPwm1Regs.TBPRD = 0x249E;           // Set period for ePWM1 (16KHz)  TBPRD = TBCLK/16KHz - 1 = 150MHz/16KHz - 1 = 9374 = 0x249E
    EPwm1Regs.TBCTL.bit.HSPCLKDIV = 0;  // Set HSPCLKDIV = 1
    EPwm1Regs.TBCTL.bit.CLKDIV = 0;     // Set CLKDIV = 1      TBCLK = SYSCLKOUT / (HSPCLKDIV 锟斤拷 CLKDIV) = 150MHz /(1 锟斤拷 1) = 150MHz
    EPwm1Regs.TBCTL.bit.CTRMODE = 0;    // count up and start
}

//
// Configure ADC
//
void
ADC_InitConfig(void)
{
    //
    // Configure ADCINT in PIE
    //
    ADC_INT_InitConfig();// Enable ADCINT in PIE

    //
    // Configure ADC
    //
    AdcRegs.ADCTRL1.bit.ACQ_PS = ADC_SHCLK;    // S/H width in ADC module periods = 16 ADC clocks
    AdcRegs.ADCTRL3.bit.ADCCLKPS = ADC_CKPS;   // ADC module clock = HSPCLK/2*ADC_CKPS   = 25.0MHz/(1*2) = 12.5MHz
    AdcRegs.ADCTRL3.bit.ADCBGRFDN = 3;         // The bandgap and reference circuitry is powered up
    AdcRegs.ADCMAXCONV.all = 0x0000;           // Setup 1 conv's on SEQ1
    AdcRegs.ADCCHSELSEQ1.bit.CONV00 = 0x1;     // Setup ADCINA1 as 1st SEQ1 conv.
    AdcRegs.ADCREFSEL.bit.REF_SEL = 0x1;       // Setup External reference, 2.048 V on ADCREFIN

    //
    // Configure ePWM
    //
    ADC_SOC_ePWM_InitConfig();
}


//
// Gpio_setup
//
void
GPIO_InitConfig(void)
{
    //
    // Make GPIO30 an output
    //
    EALLOW;
    GpioCtrlRegs.GPAPUD.bit.GPIO30 = 0;   // Enable pullup on GPIO30
    GpioCtrlRegs.GPAMUX2.bit.GPIO30 = 0;  // GPIO30 = GPIO30
    GpioCtrlRegs.GPADIR.bit.GPIO30 = 1;   // GPIO30 = output
    EDIS;
    GpioDataRegs.GPACLEAR.bit.GPIO30  = 1;  //GPIO30 = 0;
}


//
// init_mcbsp_spi
//
void
MCBSPA_InitConfig()
{
    //
    // McBSP-A register settings
    //

    //
    // Reset FS generator, sample rate generator & transmitter
    //
    McbspaRegs.SPCR2.all=0x0000;

    //
    // Reset Receiver, Right justify word, Digital loopback dis.
    //
    McbspaRegs.SPCR1.all=0x0000;

    //
    // (CLKXM = FSXM = 1)
    //
    McbspaRegs.PCR.all=0x0A00;

    McbspaRegs.SPCR1.bit.DLB = 0;

    //
    // Together with CLKXP/CLKRP determines clocking scheme
    //
    McbspaRegs.SPCR1.bit.CLKSTP = 0;

    McbspaRegs.PCR.bit.CLKXP = 0;    // CPOL = 0, CPHA = 0 rising edge no delay
    McbspaRegs.PCR.bit.CLKRP = 0;

    //
    // FSX setup time 1 in master mode. 0 for slave mode (Receive)
    //
    McbspaRegs.RCR2.bit.RDATDLY=01;

    //
    // FSX setup time 1 in master mode. 0 for slave mode (Transmit)
    //
    McbspaRegs.XCR2.bit.XDATDLY=01;

    McbspaRegs.RCR1.bit.RWDLEN1=2;   // 16-bit word
    McbspaRegs.XCR1.bit.XWDLEN1=2;   // 16-bit word

    McbspaRegs.SRGR2.all=0x2000;     // CLKSM=1, FPER = 1 CLKG periods
    McbspaRegs.SRGR1.all= 0x0001;    // Frame Width = 1 CLKG period, CLKGDV=1

    McbspaRegs.SPCR2.bit.GRST=1;     // Enable the sample rate generator
    delay_loop();                    // Wait at least 2 SRG clock cycles
    McbspaRegs.SPCR2.bit.XRST=1;     // Release TX from Reset
    McbspaRegs.SPCR1.bit.RRST=1;     // Release RX from Reset
    McbspaRegs.SPCR2.bit.FRST=1;     // Frame Sync Generator reset
}

//
// SPI receive data from MCU
//
Uint16
SPI_Receive_Data(void)
{
    Uint16 Tempt_Time,SPI_Receive_Data,Tempt_i;

    //SpiaRegs.SPICCR.bit.SPISWRESET=0;  // disable SPI
    //DSP28x_usDelay(10);
    SpiaRegs.SPICCR.bit.SPISWRESET=1;  // Enable SPI
    DSP28x_usDelay(20);
    Tempt_Time = 0;
    SpiaRegs.SPITXBUF = 0xF000;//通过发送一个无实际意义的数据0xF000（有效发送数据是高8位字节，即0xF0），启动SPI通信
    while((SpiaRegs.SPISTS.bit.INT_FLAG != 1) && (Tempt_Time<20)); //在规定时间内，等待SPI接收数据完成标志
    {
        Tempt_Time++;
    }
    if((SpiaRegs.SPISTS.bit.INT_FLAG == 1) && (Tempt_Time<20))
    {
        SPI_Receive_Data = SpiaRegs.SPIRXBUF;
        if(SPI_Receive_Data == 0x75)//判断是否是MCU发送过来的通信握手字节0x75
        {
            DSP28x_usDelay(500);
            for(Tempt_i=0;Tempt_i<282;Tempt_i++)//接收MCU发送的282个滤波参数字节
            {
                SpiaRegs.SPITXBUF = 0x9000;//通过发送一个无实际意义的数据0x9000（有效发送数据是高8位字节,即0x90），启动SPI通信
                while(SpiaRegs.SPISTS.bit.INT_FLAG != 1); //等待SPI接收数据完成标志
                SPI_Receive_DataArray[Tempt_i] = SpiaRegs.SPIRXBUF;
            }
            return 1;//全部282个滤波参数接收成功，返回1
        }
        else
        {
            return  0;//滤波参数接收不成功，返回0
        }

    }
    else
    {
        return  0;//滤波参数接收不成功，返回0
    }
    SpiaRegs.SPICCR.bit.SPISWRESET=0;  // disable SPI
}

//
// 滤波系数处理函数
//
void
Filtering_Coff_Array_Processing(void)
{
    Uint16 i,j;
    int16 tempt;

    Filter_Coff_Size = SPI_Receive_DataArray[1];
    for(i=0,j=2;i<Filter_Coff_Size;i++)
    {
        tempt = SPI_Receive_DataArray[j++];
        tempt = (tempt<<8) | SPI_Receive_DataArray[j++];
        Filtering_Coff_Array[i] = tempt;
    }
}

//
//一帧AD采样数据的FIR滤波处理
//
void FIR_Filtering(void)
{
    int32 change_tempt;
    Uint16 i,j;
    do
    {
    }
    while(FLAG_Load==1);//等待一帧AD采样数据装载完成
    FLAG_Load=1;
    if(FLAG_AB==0)
    {
        for(i=0;i<Filter_Order;i++)
        {
            AD_Array_A[i]=AD_Bankup_Array_B[i];
        }
        for(i=Filter_Order;i<AD_DA_BUF_SIZE;i++)
        {
            change_tempt=0;
            for(j=0;j<Filter_Coff_Size;j++)
            {
                change_tempt+=(int32)(Filtering_Coff_Array[j])*(Uint32)(AD_Array_A[i-j]);
            }
            DA_Array_C[DA_Array_Load_Location++]=change_tempt>>15;
        }
    }
    else
    {
        for(i=0;i<Filter_Order;i++)
        {
            AD_Array_B[i]=AD_Bankup_Array_A[i];
        }
        for(i=Filter_Order;i<AD_DA_BUF_SIZE;i++)
        {
            change_tempt=0;
            for(j=0;j<Filter_Coff_Size;j++)
            {
                change_tempt+=(int32)(Filtering_Coff_Array[j])*(Uint32)(AD_Array_B[i-j]);
            }
            DA_Array_D[DA_Array_Load_Location++]=change_tempt>>15;
        }
    }
    DA_Array_Load_Location=Filter_Order;
}


//
// adc_isr -
//
__interrupt void
adc_isr(void)
{
    Uint16 AD_Value;

    //GpioDataRegs.GPATOGGLE.bit.GPIO30 = 1;
    if(Working_Mode == 0)//判断是否是非滤波工作模式
    {
        AD_Value = AdcRegs.ADCRESULT0 >>4;//读一次AD采样数据，AD采样值共12bit，右对其
        McBSPA_TLV5636_WriteData(AD_Value);//进行一次DA转换
    }
    else//锟剿诧拷锟斤拷锟斤拷模式
    {
        if(FLAG_AB)
        {
            AD_Array_A[AD_Array_Load_Location] = AdcRegs.ADCRESULT0 >>4;
            McBSPA_TLV5636_WriteData(DA_Array_C[AD_Array_Load_Location]);
            if(AD_Array_Load_Location>AD_Bankup_Array_Start_Load_Location)
            {
                AD_Bankup_Array_A[AD_Bankup_Array_Load_Location++]=AD_Array_A[AD_Array_Load_Location];
            }
        }
        else
        {
            AD_Array_B[AD_Array_Load_Location] = AdcRegs.ADCRESULT0 >>4;
            McBSPA_TLV5636_WriteData(DA_Array_D[AD_Array_Load_Location]);
            if(AD_Array_Load_Location>AD_Bankup_Array_Start_Load_Location)
            {
                AD_Bankup_Array_B[AD_Bankup_Array_Load_Location++]=AD_Array_B[AD_Array_Load_Location];
            }
        }
        AD_Array_Load_Location++;
        if(AD_Array_Load_Location>=AD_DA_BUF_SIZE)
        {
            AD_Bankup_Array_Load_Location=0;
            AD_Array_Load_Location=Filter_Order;
            FLAG_AB=~FLAG_AB;
            FLAG_Load=0;
        }
    }

    //
    // Reinitialize for next ADC sequence
    //
    AdcRegs.ADCTRL2.bit.RST_SEQ1 = 1;         // Reset SEQ1
    AdcRegs.ADCST.bit.INT_SEQ1_CLR = 1;       // Clear INT SEQ1 bit
    PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;   // Acknowledge interrupt to PIE

    return;
}



//
// End of File
//
